//
//  UIButton+Extension.swift
//  FrameProduct
//
//  Created by delegate on 2024/2/3.
//

import UIKit

public enum ButtonPositionStyle {
    case top,
         left,
         right,
         bottom
}

public extension UIButton {
    func imagePosition(at style: ButtonPositionStyle, space: CGFloat) {
        guard let imageV = imageView else { return }
        guard let titleL = titleLabel else { return }
        //获取图像的宽和高
        let imageWidth = imageV.frame.size.width
        let imageHeight = imageV.frame.size.height
        //获取文字的宽和高
        let labelWidth = titleL.intrinsicContentSize.width
        let labelHeight = titleL.intrinsicContentSize.height
        
        var imageEdgeInsets = UIEdgeInsets.zero
        var labelEdgeInsets = UIEdgeInsets.zero
        //UIButton同时有图像和文字的正常状态---左图像右文字，间距为0
        switch style {
        case .left:
            //正常状态--只不过加了个间距
            imageEdgeInsets = UIEdgeInsets(top: 0, left: -space * 0.5, bottom: 0, right: space * 0.5)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: space * 0.5, bottom: 0, right: -space * 0.5)
        case .right:
            //切换位置--左文字右图像
            //图像：UIEdgeInsets的left是相对于UIButton的左边移动了labelWidth + space * 0.5，right相对于label的左边移动了-labelWidth - space * 0.5
            imageEdgeInsets = UIEdgeInsets(top: 0, left: labelWidth + space * 0.5, bottom: 0, right: -labelWidth - space * 0.5)
            labelEdgeInsets = UIEdgeInsets(top: 0, left: -imageWidth - space * 0.5, bottom: 0, right: imageWidth + space * 0.5)
        case .top:
            //切换位置--上图像下文字
            /**图像的中心位置向右移动了labelWidth * 0.5，向上移动了-imageHeight * 0.5 - space * 0.5
             *文字的中心位置向左移动了imageWidth * 0.5，向下移动了labelHeight*0.5+space*0.5
            */
            imageEdgeInsets = UIEdgeInsets(top: -imageHeight * 0.5 - space * 0.5, left: labelWidth * 0.5, bottom: imageHeight * 0.5 + space * 0.5, right: -labelWidth * 0.5)
            labelEdgeInsets = UIEdgeInsets(top: labelHeight * 0.5 + space * 0.5, left: -25, bottom: -labelHeight * 0.5 - space * 0.5, right: 0)
        case .bottom:
            //切换位置--下图像上文字
            /**图像的中心位置向右移动了labelWidth * 0.5，向下移动了imageHeight * 0.5 + space * 0.5
             *文字的中心位置向左移动了imageWidth * 0.5，向上移动了labelHeight*0.5+space*0.5
             */
            imageEdgeInsets = UIEdgeInsets(top: imageHeight * 0.5 + space * 0.5, left: labelWidth * 0.5, bottom: -imageHeight * 0.5 - space * 0.5, right: -labelWidth * 0.5)
            labelEdgeInsets = UIEdgeInsets(top: -labelHeight * 0.5 - space * 0.5, left: -imageWidth * 0.5, bottom: labelHeight * 0.5 + space * 0.5, right: imageWidth * 0.5)
        }
        self.titleEdgeInsets = labelEdgeInsets
        self.imageEdgeInsets = imageEdgeInsets
    }
    
    ///设置按钮渐变背景色
    func addGradient(starColor: String, endColor: String, width: CGFloat,height: CGFloat){
        let layer = CAGradientLayer()
        layer.frame = CGRect(x: 0, y: 0, width: width, height: height)
        layer.startPoint = CGPoint(x: 0, y: 0)
        layer.endPoint = CGPoint(x: 1, y: 1)
        let starColor = hexColor("\(starColor)")
        let endColor = hexColor("\(endColor)")
        layer.colors = [starColor.cgColor, endColor.cgColor]
        layer.locations = [0, 1]
        self.layer.addSublayer(layer)
      }
}


/// 扩展-扩充点击区域
extension UIButton {
    
    public typealias ButtonAction = (_ sender: UIButton) -> ()
    
    private struct RuntimeKey {
        static let clickEdgeInsets = UnsafeRawPointer.init(bitPattern: "clickEdgeInsets".hashValue)
        static var actionKey = "UIButton+LRS+ActionKey"
    }
    /// 需要扩充的点击边距
    public var clickEdgeInsets: UIEdgeInsets? {
        set {
            objc_setAssociatedObject(self, UIButton.RuntimeKey.clickEdgeInsets!, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY)
        }
        get {
            return objc_getAssociatedObject(self, UIButton.RuntimeKey.clickEdgeInsets!) as? UIEdgeInsets ?? UIEdgeInsets.zero
        }
    }
    // 重写系统方法修改点击区域
    open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        super.point(inside: point, with: event)
        var bounds = self.bounds
        let clickEdgeInsets = self.clickEdgeInsets ?? .zero
        if clickEdgeInsets != .zero {
            let x: CGFloat = -clickEdgeInsets.left
            let y: CGFloat = -clickEdgeInsets.top
            let width: CGFloat = bounds.width + clickEdgeInsets.left + clickEdgeInsets.right
            let height: CGFloat = bounds.height + clickEdgeInsets.top + clickEdgeInsets.bottom
            bounds = CGRect(x: x, y: y, width: width, height: height) //负值是方法响应范围
        }
        return bounds.contains(point)
    }
    

    @objc dynamic var actionDic: NSMutableDictionary? {
        set{
            objc_setAssociatedObject(self,&RuntimeKey.actionKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY)
        }
        get{
            if let dic = objc_getAssociatedObject(self, &RuntimeKey.actionKey) as? NSDictionary{
                return NSMutableDictionary.init(dictionary: dic)
            }
            return nil
        }
    }
    ///添加对应状态下的点击事件
    @objc dynamic func addTouchAction(action:@escaping  ButtonAction ,for controlEvents: UIControl.Event) {
        
        let eventStr = NSString.init(string: String.init(describing: controlEvents.rawValue))
        if let actions = self.actionDic {
            actions.setObject(action, forKey: eventStr)
            self.actionDic = actions
        }else{
            self.actionDic = NSMutableDictionary.init(object: action, forKey: eventStr)
        }
        
        switch controlEvents {
        case .touchUpInside:
            
            self.addTarget(self, action: #selector(touchUpInSideAction), for: .touchUpInside)
            
        case .touchUpOutside:
            
            self.addTarget(self, action: #selector(touchUpOutsideAction), for: .touchUpOutside)
        
        case .valueChanged:
            
            self.addTarget(self, action: #selector(valueChangedAction), for: .valueChanged)
            ///可以继续添加 其他状态下的点击事件……
        default:
            
            self.addTarget(self, action: #selector(touchUpInSideAction), for: .touchUpInside)
        }
    }
    
    
    @objc fileprivate func touchUpInSideAction(btn: UIButton) {
        if let actionDic = self.actionDic  {
            if let touchUpInSideAction = actionDic.object(forKey: String.init(describing: UIControl.Event.touchUpInside.rawValue)) as? ButtonAction{
                touchUpInSideAction(self)
            }
        }
    }
    
    @objc fileprivate func touchUpOutsideAction(btn: UIButton) {
        if let actionDic = self.actionDic  {
            if let touchUpOutsideButtonAction = actionDic.object(forKey:   String.init(describing: UIControl.Event.touchUpOutside.rawValue)) as? ButtonAction{
                touchUpOutsideButtonAction(self)
            }
        }
    }
    
    @objc fileprivate func valueChangedAction(btn: UIButton) {
        if let actionDic = self.actionDic  {
            if let touchUpOutsideButtonAction = actionDic.object(forKey:   String.init(describing: UIControl.Event.valueChanged.rawValue)) as? ButtonAction{
                touchUpOutsideButtonAction(self)
            }
        }
    }
    
    /// 快捷调用 事件类型为 .touchUpInside
    @objc func add_Action(_ action:@ escaping ButtonAction) {
        self.addTouchAction(action: action, for: .touchUpInside)
    }
    
    
    /// 这俩方法就比较的牛了 让每一个点击事件都返回自身，为链式调用做准备
    @discardableResult
    public func addTouchUpInSideButtonAction(_ action: @escaping ButtonAction) -> UIButton {
        self.addTouchAction(action: action, for: .touchUpInside)
        return self
    }
    
    @discardableResult
    public func addTouchUpOutSideButtonAction(_ action: @escaping ButtonAction) -> UIButton {
        self.addTouchAction(action: action, for: .touchUpOutside)
        return self
    }
}


